/*
 * Copyright (c) 2007-2008, Thomas Krause (tho.krause@gmail.com)
 * 
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 * 
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice,
 *       this list of conditions and the following disclaimer in the documentation
 *       and/or other materials provided with the distribution.
 *     * Neither the name of gidoo nor the names of its contributors may be used to
 *       endorse or promote products derived from this software without specific
 *       prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.gidoo.wickettools;

/**
 * This class produces a visual diff using XHTML as output.
 * It uses it's own very simple diff-algorithm which will always show the
 * correct old and new versions but may be "wrong" in the decision wether 
 * a line was changed, deleted or inserted in certain situations.
 * @author <a href="mailto:tho.krause@gmail.com">Thomas Krause</a>
 */
public class XHTMLDiff
{

  /**
   * Creates a new instance of XHTMLDiff
   */
  public XHTMLDiff()
  {
  }
  
  /**
   * Compares s1 (older) and s2 (newer).
   *
   * @return XHTML-Code (without head, body and especially without table and th)
   */
  public static String doDiff(String s1, String s2)
  {
    if(s1 == null || s2 == null)
      return "";
    
    // mask special XHTML characters
    s1 = maskXHTML(s1);
    s2 = maskXHTML(s2);
    
    String[] split1 = s1.split("(\\r\\n)|(\\n)|(\\r)");
    String[] split2 = s2.split("(\\r\\n)|(\\n)|(\\r)");
            
    int i=0;
    int j=0;
    
    String left = "";
    String right = "";
    
    while(i < split1.length || j < split2.length)
    {
      
      if(i < split1.length && j < split2.length && split1[i].equals(split2[j]))
      {
        left += split1[i] + "<br />";
        right += split2[j] + "<br />";
        
        i++;
        j++;
      }
      else
      {
        // test for insert
        boolean wasInserted = false;
        int j_ins = j + 1;
        
        if(j >= split1.length)
        {
          // inserted at the end
          wasInserted = true;
          j_ins = split2.length;
        }
        else
        {
          
          while(j_ins < split2.length)
          {
            if(i >= split1.length || split1[i].equals(split2[j_ins]))
            {
              wasInserted = true;
              break;
            }
            j_ins++;
          }
        }
        
        if(wasInserted)
        {
          while(j < j_ins)
          {
            right += "<span style=\"color:green\">";
            right += split2[j];
            right += "</span><br />";
            
            left += "<br />";
            
            j++;
          }
        }
        else
        {
          // test for delete
          boolean wasDeleted = false;
          int i_del = i + 1;
          while(i_del < split1.length)
          {
            if(j >= split2.length || split1[i_del].equals(split2[j]))
            {
              wasDeleted = true;
              break;
            }
            i_del++;
          }
          if(wasDeleted)
          {
            while(i < i_del)
            {
              left += "<span style=\"color:red;text-decoration:line-through;\">";
              left += split1[i];
              left += "</span><br />";
              
              right += "<br />";
              
              i++;
            } 
          }
          else
          {
            // must have been a change 
            left += "<span style=\"color:orange;\">";
            if(i < split1.length)
            {
              left += split1[i];
            }
            left += "</span><br />";
            right += "<span style=\"color:orange;\">";
            if(j < split2.length)
            {
              right += split2[j];
            }
            right += "</span><br />";
            
            i++;
            j++;
          }
        }
        
      }
      
    }
    
    String result = "<tr><td><pre>" + left + "</pre></td><td><pre>" + right + 
      "</pre></td></tr>";
    
    return result;
  }
  
  public static String maskXHTML(String s)
  {
    String result = "" + s;
    result = result.replaceAll("<", "&lt;");
    result = result.replaceAll(">", "&gt;");
    
    return result;
  }
}
